#include "round.h"

//    Acutal initial muzzle velocity: 18 m/s. 
//    I slowed it down so we can see it fly.
float Round::initSpeed = 5.0f;
//    Acceleration due to gravity. Also slowed from reality.
float Round::acceleration = -.01f;
float Round::offset = 5;

vector<Round*> Round::shells;
Camera* Round::cam = NULL;

Round::Round(float elevation, float deflection, bool follow)
{
   if (follow)
      cam = new Camera();

   d = deflection;
   e = elevation;

   time(&timeUpdate);
   
   direction[x] = sin(d * M3D_PI_DIV_180);
   direction[y] = sin(-e * M3D_PI_DIV_180);
   direction[z] = cos(d * M3D_PI_DIV_180);

   location[x] = direction[x] * 10.324;
   location[y] = direction[y] * 10.324 + 3.25;
   location[z] = direction[z] * 10.324 - 2.2;

   componentSpeed[x] = initSpeed * direction[x];
   componentSpeed[y] = initSpeed * direction[y];
   componentSpeed[z] = initSpeed * direction[z];

   float camLoc[3];
   camLoc[x] = location[x] + direction[x] * offset;
   camLoc[y] = location[y] + direction[y] * offset;
   camLoc[z] = location[z] + direction[z] * offset ;

   if (cam)
   {
      cam->UpdateLocation(camLoc[x], camLoc[y], camLoc[z]);
      cam->UpdateDirection(camLoc[x] + camLoc[x]*direction[x],
         camLoc[y] + camLoc[y]*direction[y],
         camLoc[z] + camLoc[z]*direction[z]);
   }
}

void Round::Draw()
{
   //
   glEnable(GL_COLOR_MATERIAL);
   glPushMatrix();
      glTranslatef(location[x], location[y], location[z]);
      glRotatef(e, 1, 0, 0);
      glRotatef(d, 0,1,0);

      //    Base
      glColor3fv(LightGray);
      gluDisk(gluNewQuadric(), 0, .2, 32, 1);
      glColor3fv(White);
      gluCylinder(gluNewQuadric(), .2, .3, .3, 32, 1);
      
      //    White Middle
      glTranslatef(0, 0, 0.3f);
      gluCylinder(gluNewQuadric(), .3, .3, .5, 32, 1);

      glColor3fv(Blue);

      //    Blue Middle through Tip
      glTranslatef(0, 0, 0.5f);
      gluCylinder(gluNewQuadric(), .3, .3, .5, 32, 1);

      glTranslatef(0, 0, 0.5);
      gluCylinder(gluNewQuadric(), .3, .28, .2, 32, 1);

      glTranslatef(0, 0, .2);
      gluCylinder(gluNewQuadric(), .28, .25, .3, 32, 1);

      glTranslatef(0, 0, .3);
      gluCylinder(gluNewQuadric(), .25, .20, .2, 32, 1);

      glTranslatef(0, 0, .2);
      gluCylinder(gluNewQuadric(), .20, .15, .2, 32, 1);

      glTranslatef(0, 0, .2);
      gluCylinder(gluNewQuadric(), .15, .1, .15, 32, 1);

      //    Fuse is black.
      glColor3fv(Black);
      glTranslatef(0, 0, .15);
      gluCylinder(gluNewQuadric(), .1, 0, .2, 32, 1);
   glPopMatrix();
   glDisable(GL_COLOR_MATERIAL);
}

void Round::AddRound(float e, float d, bool follow)
{
   shells.push_back( new Round(e, d, follow) );
   shells.back()->Draw();
}

void Round::Update()
{
   float camLoc[3];
   time_t currentTime;
   for (int i = 0; i < shells.size(); ++i)
   {
      Round* current = shells[i];

      if (current->alive == false)
         continue;

      current->componentSpeed[y] += acceleration;

      time(&currentTime);

      if (difftime(currentTime, current->timeUpdate) >= 1.0 && current->componentSpeed[y])
      {
         current->location[x] += current->componentSpeed[x];
         current->location[y] += current->componentSpeed[y];
         current->location[z] += current->componentSpeed[z];

         camLoc[x] = current->location[x] + current->direction[x] * offset;
         camLoc[y] = current->location[y] + current->direction[y] * offset;
         camLoc[z] = current->location[z] + current->direction[z] * offset;

         if (cam)
         {
            cam->UpdateLocation(camLoc[x], camLoc[y], camLoc[z]);
            cam->UpdateDirection(camLoc[x] + camLoc[x]*current->direction[x],
               camLoc[y] + camLoc[y]*current->direction[y],
               camLoc[z] + camLoc[z]*current->direction[z]);
         }

         if (current->location[y] <= 1)
         {
            current->componentSpeed[x] = current->componentSpeed[y] = current->componentSpeed[z] = 0;
            current->alive = false;
            delete cam;
            cam = NULL;
         }
         time(&current->timeUpdate);
      }
   }
}
void Round::DrawRounds()
{
   for (int i = 0; i < shells.size(); ++i)
      shells[i]->Draw();
   if (shells.size())
      Update();
}

Camera* Round::GetCamera() { return cam; }
